#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
//下面都是本地文件
#include "../head/default.h"         //define 宏定义及static变量                                      
#include "../head/log.h"         //define 宏定义及static变量 


void f_logging(enum LogLevel level, const char *fmt, ...);
int f_my_strncpy(char *string, int n);
int f_default_check_comm(char *bl_comm[], int max_index, char comm[]);
int f_get_md5(char str[], char res_md5[]);
int f_replace_string(char * source_str,char * targ_str,char *val);

extern char *bl_default_comm[20];

int f_client(int argc, char *argv[]) {

    int sock_fd;
    struct sockaddr_in server_addr;
    struct hostent *host;
    char buffer[VAR_MAX_LEN];

    if (strlen(argv[1]) == 0) {
        f_logging(ERROR, "CLIENT --> Need hostname or IP addr!");
        return -1;
    }


    if ((host = gethostbyname(argv[1])) == NULL) {
        f_logging(ERROR, "CLIENT --> gethostbyname!");
        return -1;
    }

    if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        f_logging(ERROR, "CLIENT --> The socket abnormal!");
        return -1;
    }

    memset(&server_addr, 0x00, sizeof(struct sockaddr_in));
    server_addr.sin_family  = AF_INET;
    server_addr.sin_port    = htons(atoi(argv[2]));
    server_addr.sin_addr    = *((struct in_addr *) host -> h_addr);


    if (connect(sock_fd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)) == -1) {
        f_logging(ERROR, "CLIENT --> The connection abnormal!");
        return -1;
    }

    if (strlen(argv[3]) != 0) {
        strcpy(buffer, argv[3]);
    } else {
        while (1) {
            printf("\033[32m%s:%s \033[0mshell > ", argv[1], argv[2]);
            fgets(buffer, VAR_TMP_MAX_LEN, stdin);
            if (strlen(buffer) > 2) {
                break;
            } else if (strlen(buffer) > VAR_TMP_MAX_LEN) {
                printf("输入的命令长度是 : %zu\n\n超过最大长度 %d 限制!\n\n\n\n", strlen(buffer), VAR_TMP_MAX_LEN);
                continue;
            }
        }

        f_my_strncpy(buffer, (int)strlen(buffer) - 1);
        if (strcmp(buffer, "exit") == 0) {
            printf("\033[33mByeBye!\033[0m\n");
            return 0;
        }
    }

    //检查命令是否合法
    int mark = f_default_check_comm(bl_default_comm, BL_MAX_COUNT, buffer);
    if (mark != 0) { //mark 不等于0 检查不通过
        return -1;
    }
    
    char client_md5[32], tmp_state[VAR_MAX_LEN * 3], tmp_buffer[VAR_MAX_LEN];
    int state_mark = 0 , concat = 0; //state_mark读取fd内容, 进行状态判断, 这是开关, 表示仅判断一次, 避免重复判断
    int res_state = -1; //命令执行状态码, 0表示成功, 非0表示失败
    f_get_md5(buffer, client_md5);
    sprintf(buffer,"%s/%s/%s/%zu", buffer, client_md5, argv[6], strlen(buffer) + strlen(argv[6]) + 32 + 2);
    write(sock_fd, buffer, strlen(buffer));
    memset(buffer, 0x00, sizeof(buffer));
    ssize_t nbytes;
    while (1) { //等待服务端返回结果, 然后将结果输出, 因为这里是用了1024分段写, 所以需要循环
        memset(tmp_buffer, 0x00, sizeof(tmp_buffer));
        if ((nbytes = read(sock_fd, tmp_buffer, VAR_MAX_LEN)) == -1) {
            f_logging(ERROR, "CLIENT --> Failed to read message!");
            return -1;
        }
        buffer[nbytes] = '\0';

        if (concat % 2 == 0 && state_mark == 0) { //两个单位拼接在一起, 避免因为被拆成两次, 偶数次就重置内存, 奇数就拼接
            memset(tmp_state, 0x00, sizeof(tmp_state));
        }

        if (state_mark == 0) {
            concat += 1;
            strcpy(tmp_state, tmp_buffer);   //追加
        }
        
        if (strstr(tmp_state, "{\"STATE\":0}") && state_mark == 0) {
            res_state = 0;
            state_mark = 1;
        }

        f_replace_string(tmp_buffer, "{\"STATE\":0}",""); //删除正常状态码

        if (strstr(tmp_buffer, "CLIENT -->")) {
            f_logging(WARN, tmp_buffer);
        } else {
            printf("%s", tmp_buffer);
        }
    
        if (strcmp(tmp_buffer, "\0") == 0) { //结束标志
            printf("\n");
            break;
        }
    }
    close(sock_fd);
    if (res_state == 0) {
        return 0;
    } else {
        return -1;
    }
}
